package cn.xin.base.service.impl;

import cn.xin.base.constant.PhoneConstant;
import cn.xin.base.dto.PhoneRegisterDto;
import cn.xin.base.dto.SmsCodeDto;
import cn.xin.base.service.VerifyCodeService;
import cn.xin.base.util.BussinessException;
import cn.xin.base.util.SendMsgUtil;
import cn.xin.base.util.VerifyCodeUtils;
import cn.xin.user.domain.Logininfo;
import cn.xin.user.domain.User;
import cn.xin.user.mapper.LogininfoMapper;
import cn.xin.user.mapper.UserMapper;
import com.mysql.cj.log.Log;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    LogininfoMapper logininfoMapper;

    /**
     *
     * @param imageCodeKey
     * @return
     * @throws IOException
     */
    @Override
    public String imageCode(String imageCodeKey) throws IOException {
        //校验参数

        //生成图形验证码
        String imageCode = VerifyCodeUtils.generateVerifyCode(4);
        //存到redis
        redisTemplate.opsForValue().set(imageCodeKey,imageCode,3, TimeUnit.MINUTES);
        //返回图形验证码
        return VerifyCodeUtils.VerifyCode(80,30,imageCode);
    }

    /**
     * 手机验证码
     * @return
     */
    @Override
    public void smsCode(SmsCodeDto smsCodeDto) {

        //判断是绑定还是注册
        if ("binder".equals(smsCodeDto.getType())){
            // 发送短信
            this.sendSms(PhoneConstant.BINDER_REDIS_KEY,smsCodeDto);
        }else if ("register".equals(smsCodeDto.getType())){
            // 图形验证码验证
            this.imageVerify(smsCodeDto);
            // 发送短信
            this.sendSms(PhoneConstant.REDIS_KEY,smsCodeDto);
        }
    }

    /**
     * 图形验证码
     * @param smsCodeDto
     */
    private void imageVerify(SmsCodeDto smsCodeDto) {
        //校验参数
        //判断图形验证码是否过期和是否正确
        String imageCode = (String) redisTemplate.opsForValue().get(smsCodeDto.getImageCodeKey());
        //判断图形验证码是否为空 StringUtils.isBlank()校验一个String类型的变量是否为空
        if (StringUtils.isBlank(imageCode) || !smsCodeDto.getImageCodeValue().equals(imageCode)){
            throw new BussinessException("图形验证码错误");

        }

        //判断手机号是否注册过
        User userPhone = userMapper.findByPhone(smsCodeDto.getPhone());
        if (userPhone != null){
            throw new BussinessException("手机号已注册，请登录");
        }

        //删除图形验证码
        redisTemplate.delete(smsCodeDto.getImageCodeKey());
    }

    /**
     * 手机验证码
     * @param smsCodeDto
     */
    private void sendSms(String redisKey,SmsCodeDto smsCodeDto) {
        //获取手机验证码过期时间
        Long smsCodeTime = redisTemplate.getExpire(String.format(PhoneConstant.REDIS_KEY, smsCodeDto.getPhone()));
        //判断手机验证码是否为空，验证码时间是否大于60秒
        if (smsCodeTime != null && smsCodeTime > (PhoneConstant.REDIS_TTL - 1) * 60){
            throw new BussinessException("手机验证码过期");
        }

        //是否需要重置手机验证码
        //获取手机验证码
        String smsCode =(String) redisTemplate.opsForValue().get(String.format(PhoneConstant.REDIS_KEY, smsCodeDto.getPhone()));
        //判断是否有验证码,第一次注册的时候和redis存的验证码时间过期
        if (StringUtils.isBlank(smsCode)){
            //没有就给它一个验证码
            smsCode = VerifyCodeUtils.generateVerifyCode(4);
        }

        log.info("手机验证码:{}",smsCode);

        //将手机验证码存档redis中 K-V-时间
        redisTemplate.opsForValue().set(String.format(PhoneConstant.REDIS_KEY, smsCodeDto.getPhone()),
                smsCode,
                PhoneConstant.REDIS_TTL,TimeUnit.MINUTES);

        //发送手机短信验证码
        //SendMsgUtil.send(smsCodeDto.getPhone(),smsCode);
    }

    /**
     *手机注册
     */
    @Override
    public void phoneRegister(PhoneRegisterDto dto) {
        //检验参数

        //获取手机验证码
        String smsCode = (String) redisTemplate.opsForValue()
                .get(String.format(PhoneConstant.REDIS_KEY, dto.getPhone()));

        //判断手机验证码是否过期，是否正确
        if (StringUtils.isBlank(smsCode) || !dto.getSmsCode().equals(smsCode)){
            throw new BussinessException("验证码有误");
        }

        //判断两次密码是否一致
        if (!dto.getPassword().equals(dto.getPasswordRepeat())){
            throw new BussinessException("密码不一致");
        }

        //判断手机是否注册过
        User phone = userMapper.findByPhone(dto.getPhone());
        if (phone != null){
            throw new BussinessException("手机号已注册，请登录");
        }

        //保存数据（用户）
        User user = dto.getUser();
        //保存数据（登录信息）
        Logininfo logininfo = new Logininfo();

        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        logininfo.setDisable(1);

        logininfoMapper.add(logininfo);

        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);

    }



}
